<template>
    <div class="hello">
        <h3>泛型进阶</h3>
        <h3>泛型函数式接口</h3>
        <h3>泛型类</h3>

    </div>
</template>

<script  lang="ts" >
    import { defineComponent } from 'vue'
    import {inputNumberEmits} from "element-plus";

    export default defineComponent({
            name: 'HelloWorld',
            props: {
                msg: String
            },
            setup(props,context){ // setup 不允许前面加async
                let str:string = "string"


                function identity<Type>(arg: Type): Type {
                    console.log(arg)
                    return arg
                }
                let myIdentity: <Type>(arg: Type) => Type = identity
                myIdentity<number>(20)

                /*指定函数类型*/
                let myIdentity2: GenericIdentityFn<string> = identity
                myIdentity2('ds')

                /*泛型函数式接口*/
                interface GenericIdentityFn<Type> {
                    (arg: Type): Type
                }
                // 实现这个函数式接口
                let myIdentity3: GenericIdentityFn<number> = function(arg: number) :number{
                    return arg
                }

                // 动物泛型类  <可以指定多种类型>  泛型接口
                interface Animal<T,U,R>{
                    name:T
                    age:U
                    type?:T
                    eat?:(x: T, y: T) => T
                }
                let instance:Animal<string,number,boolean> ={
                    name:"zs",
                    age:20,
                    type:"string"
                }
                console.log(instance);
                // 泛型类
                class Animal2<T,R,U>{
                    name:T
                    age:R
                    // numLegs: number = 4
                    numLegs: number= 4
                    weiba: number
                    type?:R
                    constructor(name:T,age:R,weiba:number=1) {
                        this.name = name
                        this.age = age
                        this.weiba = weiba
                    }
                }
                let instance2:Animal2<any, any, any> = new Animal2<any, any, any>("WF","20")
                console.log(instance2);

                // keyof的使用
                // Key 类型必须是T类型的某个key 值
                 function getProperty<T, Key extends keyof T>(obj: T, key: Key) {
                     console.log(obj[key]);
                     return obj[key]
                }

                let x = {
                  a: 1,
                  b: 2,
                  c: 3,
                  d: 4
                }
                getProperty(x, 'a')// 只能是abcd
                // getProperty(x, 'm') // 报错
                type Point = { x: number, y: number }
                type P = keyof Point  // 将Point 中的key 作为联合类型 x|y
                const p1:P = 'x'
                const p2:P = 'y'
                // const p3:P = 'z'  //error
                type Arrayish = { [index: number]: number }
                type A = keyof Arrayish // number
                const a123:A = 0

                type Mapish = { [prop: string]: boolean }  // 
                type M = keyof Mapish  // 索引number 和 string  number是默认有的  有印象即可
                const m1:M = 's'
                const m2:M = 100
                // const m3:M = true  // error

                // 条件类型约束:返回数组元素类型或者 基本类型
                type Flatten<T> = T extends Array<any>? T[number] : T    // T[number] 返回数组里面元素的类型
                // type Flatten<T> = T extends Array<infer U>? U: never    // infer 替代写法
                // type Str = string
                type Str = Flatten<string[]> //返回string[] 数组元素的类型
                let x0:Str ="123"
                // type Num = number
                type Num = Flatten<number[]>
                let x2:Num =45

                type Bol = Flatten<boolean[]>
                let x3:Bol =true

                type N = Flatten<number>
                let x4:N = 100
                return {
                    str
                }
            }
        }
    )
</script>

<style scoped>

</style>
